using System;
using System.Reflection;
using System.Collections.Generic;

namespace Elephant.Framework
{
    /// <summary>
    /// Represents the base of a factory.
    /// </summary>
    public abstract class Factory
    {
        /// <summary>
        /// Finds the best matching constructor, given a type and a range of parameters.
        /// </summary>
        /// <param name="type"></param>
        /// <param name="parameters"></param>
        /// <returns></returns>
        protected static ConstructorInfo GetBestMatchingConstructor(Type type, object[] parameters)
        {
            ConstructorInfo[] constructors = type.GetConstructors();

            // find the signatures that has the same amount of parameters, as the parameters passed
            List<ConstructorInfo> countMatches = new List<ConstructorInfo>();

            for (int i = 0; i < constructors.Length; i++) {
                if (constructors[i].GetParameters().Length == parameters.Length) {
                    countMatches.Add(constructors[i]);
                }
            }

            ConstructorInfo bestMatch = constructors[0];

            // find the best matching signature (the best match can still be an invalid signature)
            if (countMatches.Count > 0) {
                int indexOfBest = -1, currentBestMatches = -1;

                for (int i = 0; i < countMatches.Count; i++) {
                    ParameterInfo[] pi = countMatches[i].GetParameters();

                    int n = 0;

                    for (int j = 0; j < pi.Length; j++) {
                        if (pi[j].ParameterType.Equals(parameters[j].GetType())) {
                            n++;
                        }
                    }

                    if (n > currentBestMatches) {
                        currentBestMatches = n;

                        indexOfBest = i;
                    }
                }

                bestMatch = countMatches[indexOfBest];
            }

            return bestMatch;
        }
    }
}
